package com.soupinabox;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * IRCConnection.java
 * <p/>
 * Author:  Taw
 * Date:    4/21/14
 */
public class IRCConnection extends Thread {

    public Socket socket;
    public BufferedReader in;
    public BufferedWriter out;

    public String nick;
    String pass;

    ArrayList<Inventory> inventories = new ArrayList<Inventory>();

    ArrayList<String> outbound = new ArrayList<String>();

    boolean validated = false;
    boolean connected = true;



    long FLOOD_DELAY = 2000;
    long TIME_OUT_LENGTH = 240*1000;
    //long UPDATE_PING = 30*1000;  //TODO: MOD VERSION ONLY
    long UPDATE_PING = 60*1000;  //TODO: HOST VERSION ONLY

    long lastping=0;
    long lastmessage=0;


    boolean sentping = true;


    //$1 = hostname
    public static final Pattern MSG_PATTERN = Pattern.compile("^(?::?(?:([^ !]+)(?:!\\S+)?) )?([A-Za-z0-9]+)(?: ([^ ]+))?(?: :?([^$]*))$");

    public static final Pattern CMD_PATTERN = Pattern.compile("^[^\\$]*\\$(\\w+) *(.*)");

    public void run() {
        try{
            validated = validate();
            if(!validated){
                    out.write("\r\nQUIT :INVALID\r\n");
                    out.flush();
                    System.out.println("INVALID");
                    socket.close();
                    out.close();
                    in.close();
                    return;
            }

            socket.close();
            out.close();
            in.close();

            socket=new Socket("irc.rizon.net",6667);
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            nick="^_"+nick;

            out.write("NICK "+nick+"\r\n");
            out.flush();

            String line = null;
            long t=System.currentTimeMillis();
            while ((line = in.readLine( )) != null && System.currentTimeMillis()-t < 15*1000) {
                if (line.indexOf("004") >= 0) {
                    // We are now logged in.
                    break;
                }
                else if (line.indexOf("433") >= 0) {
                    System.out.println("Nickname is already in use.");
                    //TODO: Report double connection
                    return;
                }
            }
            if(System.currentTimeMillis()-t>=15*1000){
                //Connection attempt timed out after 15 seconds
                //TODO: Close connection with timeout error
                return;
            }

            //TODO: Notify connection successful
            connected = true;

            String lastJoined="";

            while(System.currentTimeMillis()-lastping < TIME_OUT_LENGTH && connected && (line = in.readLine()) != null){
                lastping=System.currentTimeMillis();
                sentping=false;
                Matcher m=MSG_PATTERN.matcher(line);
                String from = m.group(1);
                String cmd = m.group(2);
                String mid = m.group(3);
                String trail = m.group(4);
                try{
                    if(cmd.equalsIgnoreCase("PONG"))System.out.println(line);
                    if(cmd.equalsIgnoreCase("PRIVMSG") && mid.equalsIgnoreCase(nick) && trail.toUpperCase().startsWith("\u0001VERSION ")){
                        out.write("NOTICE "+from+ " : \u0001VERSION BoI Item Inventory "+ItemTracker.VERSION+"\r\n");
                        out.flush();
                    }
                    if(cmd.equalsIgnoreCase("PING")){
                        System.out.println(line);
                        out.write("PONG " + ":" + trail + "\r\n");
                        out.flush();
                    } else if(cmd.equalsIgnoreCase("JOIN")){
                        if(mid.equalsIgnoreCase(nick)){
                            lastJoined=trail;
                        }
                    } else if(cmd.equals("324")){
                        //channel mode incoming
                        String affectedChan=trail.split(" ")[0];
                        if(!trail.split(" ")[1].contains("s")){
                            sendChannelMode(affectedChan,"+s");
                        }
                    } else if(cmd.equalsIgnoreCase("MODE")){
                        //mode change incoming
                    } else if(cmd.equalsIgnoreCase("PRIVMSG")){
                        //TODO: write message stuff
                        System.out.println(line);
                        Matcher cm=CMD_PATTERN.matcher(trail);

                    }
                }catch(Exception e){
                    e.printStackTrace();
                }

                sleep(50);
            }

        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void sendChannelMode(String  chan,String modes){
        outbound.add("MODE "+chan+" "+modes);
    }

    public void addTracker(Inventory t){

    }



    public void setPass(String s){
        pass = s;
    }
    public void setNick(String s){
        nick = s;
    }


    public boolean validate(){
        try{
            socket = new Socket("irc.twitch.tv",6667);
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            out.write("PASS "+pass+"\r\n");
            out.write("NICK "+nick+"\r\n");
            out.flush();

            String line = null;
            long t=System.currentTimeMillis();
            while ((line = in.readLine( )) != null && System.currentTimeMillis()-t < 15*1000) {
                if (line.indexOf("004") >= 0) {
                    // We are now logged in.
                    return true;
                }
                else if (line.indexOf("433") >= 0) {
                    //this should never happen on twitch servers...
                    System.out.println("Nickname is already in use.");
                    return false;
                }
            }
            if(System.currentTimeMillis()-t>=15*1000){
                return false;
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }

    public boolean canSendMessage(){
        return System.currentTimeMillis() - lastmessage > FLOOD_DELAY;
    }

}
